"""
Case Type   : 故障&可靠性测试
Case Name   : 配置文件丢失恢复后，备机重建接收ctrl+c
Create At   : 2020/12/08
Owner       : liumin
Description :
    1. 备机删除配置文件
    2. 备机重建
    3. 恢复配置文件
    4. 备机重建，过程中接收ctrl+c
    5. 备机再次重建
    6. 查看主备状态
Expect      :
    1. 执行成功，无返回信息
    2. 执行失败
    3. 执行成功，无返回信息
    4. 执行被中断
    5. 执行成功
    6. 主备状态正常
History     :
    Modified by peilinqian 优化用例，备机重建取消前等待5~10s内随机时间
    Modified by ningyali 优化用例，解决不一致问题
"""
import random
import unittest
import os
from yat.test import Node
from yat.test import macro
import sys
sys.path.append(sys.path[0] + "/../")
from testcase.utils.CommonSH import *
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.ComThread import ComThread


class ModifyAudit(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} 开始执行-----')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.sta1_sh = CommonSH('Standby1DbUser')
        self.pri_user = self.pri_sh.node
        self.sta1_user = self.sta1_sh.node
        self.Constant = Constant()
        self.common = Common('PrimaryRoot')
        self.conf_file = os.path.join(macro.DB_INSTANCE_PATH,
                                      'postgresql.conf')
        self.conf_bak_file = self.conf_file.replace('conf', 'conf_dbsys178')
        self.check_conf_cmd = f"if [ -f {self.conf_file} ];" \
                              f"then echo 'exists';" \
                              f"else echo 'not exists';" \
                              f"fi;"
        self.check_conf_bak_cmd = self.check_conf_cmd.replace(
            self.conf_file, self.conf_bak_file)
        self.db_status = None

    def test_basebackup(self):
        text = '-----step1:备机删除配置文件; expect:成功-----'
        self.log.info(text)
        shell_cmd = f"cp {self.conf_file} {self.conf_bak_file};" \
                    f"rm -rf {self.conf_file};" \
                    f"{self.check_conf_cmd}"
        self.log.info(shell_cmd)
        res = self.sta1_user.sh(shell_cmd).result()
        self.log.info(res)
        self.assertIn('not exists', res, '执行失败:' + text)

        text = '-----step2:备机重建; expect:失败-----'
        self.log.info(text)
        builf_res1 = self.sta1_sh.executeGsctl(
            'build', self.Constant.BUILD_SUCCESS_MSG)
        self.assertFalse(builf_res1, '执行失败:' + text)

        text = '-----step3:恢复配置文件; expect:成功-----'
        self.log.info(text)
        shell_cmd = f"mv {self.conf_bak_file} {self.conf_file};" \
                    f"{self.check_conf_bak_cmd}"
        self.log.info(shell_cmd)
        res = self.sta1_user.sh(shell_cmd).result()
        self.log.info(res)
        self.assertIn('not exists', res, '执行失败:' + text)

        text = '-----step4:备机重建，过程中接收ctrl+c; expect:重建失败-----'
        self.log.info(text)
        self.log.info('-----备机重建-----')
        build_thread = ComThread(self.sta1_sh.executeGsctl,
                                 args=('build',
                                       self.Constant.BUILD_SUCCESS_MSG,))
        build_thread.setDaemon(True)
        build_thread.start()
        time.sleep(random.randint(5, 10))

        self.log.info('-----ctrl+c-----')
        result = self.common.kill_pid_keyword('build', '2', self.sta1_user)
        self.log.info(result)

        build_thread.join(60 * 60)
        build_res2 = build_thread.get_result()
        self.log.info(build_res2)
        self.assertFalse(build_res2, '执行失败:' + text)

        text = '-----step5:备机再次重建; expect:重建成功-----'
        self.log.info(text)
        status = self.pri_sh.getDbClusterStatus('detail')
        self.log.info(status)
        build_res3 = self.sta1_sh.executeGsctl(
            'build', self.Constant.BUILD_SUCCESS_MSG)
        self.assertTrue(build_res3, '执行失败:' + text)

        text = '-----step6:查看主备状态; expect:状态正常-----'
        self.log.info(text)
        self.db_status = self.pri_sh.getDbClusterStatus('status')
        self.assertTrue(self.db_status, '执行失败' + text)

    def tearDown(self):
        self.log.info('-----this is tearDown-----')
        if not self.db_status:
            self.log.info('-----异常情况，尝试再次恢复备机-----')
            self.log.info('-----恢复配置文件-----')
            shell_cmd = f"mv {self.conf_bak_file} {self.conf_file};"
            res = self.sta1_user.sh(shell_cmd).result()
            self.log.info(res)
            self.log.info('-----备机重建-----')
            res = self.sta1_sh.executeGsctl(
                'build', self.Constant.BUILD_SUCCESS_MSG)
            self.log.info(res)
        self.log.info(f'-----{os.path.basename(__file__)} 执行结束-----')